package com.Astart 
{
	import flash.geom.Point;
	/**
	 * ...
	 * @author weoweo
	 */
	public class AcorrsLineGrid 
	{
		
		private var _grid:Grid;
		private var _astartNodes:Array;
		
		public function AcorrsLineGrid(g:Grid,ns:Array=null) 
		{
			this._grid = g;
			
			this._astartNodes = ns;
			nodes = _grid.nodes;
			nodeWidth = _grid.nodeWidth;
			nodeHeight = _grid.nodeHeight;
			arrange = new Arrange();
			arrange.key = "f";
		}
		public function getPsnode(arr:Array = null):Array {
			//trace("asdf")
			//trace("------------------------------------ getPsnode");
			
			
			if (arr == null) arr = _astartNodes;
			if (arr == null|| _grid==null) throw new Error("没有合适节点可供计算：in AcorrsLineGrid");
			var len:uint = arr.length;
			if (len<3) return arr;
			var psArr:Array = [];
			var node:Node = arr[0] as Node;
			var endNode:Node = arr[len-1]as Node;
			var index:uint = 0;
			psArr.push(node);
			while (node != endNode) {
				
				for (var i:int = len-1; i > index; i-- ) {
					var test:Node = arr[i] as Node;
					var neigbor:Boolean = Boolean((i - index) == 1);
					if (neigbor || isCorrsed(node, test)) {
						//trace("Node " + i+"  "+(neigbor));
						node = test;
						index = i;
						psArr.push(test);
						break;
					}
				}
			}
			
			return psArr;
		}
		
	
		private var nodes:Array;
		private var nodeWidth:Number;
		private var nodeHeight:Number;
		private var arrange:Arrange;
		
		//---直线方程系数
		private var _k:Number;
		private var _b:Number;
		private var _isPanX:Boolean = false;
		private var _panXvalue:int;
		private var _isPanY:Boolean = false;
		private var _panYvalue:int;
	
		private  function isCorrsed(s:Node, e:Node):Boolean {
			//_grid.nodesRest();
			if (!s || !e) return false;
			//var ep:Point = new Point(e.x*nodeWidth+0.2,e.y*nodeHeight+0.2);
			_isPanX = s.y == e.y ;
			_isPanY = s.x == e.x;
			if (_isPanX || _isPanY) {
				if (_isPanX) _panXvalue =s.y * nodeHeight ;
				if (_isPanY) _panYvalue = s.x * nodeWidth;
			}else {
				_k = ((e.y - s.y) * nodeHeight) / ((e.x - s.x) * nodeWidth);
				_b = (e.y + 0.5) * nodeHeight - (((e.x + 0.5) * nodeWidth) * _k);
			}
			
			
			var minx:int = Math.min(e.x, s.x);
			var maxx:int = Math.max(e.x, s.x);
			var miny:int = Math.min(s.y, e.y);
			var maxy:int = Math.max(s.y, e.y);
			
			var startPx:int = (minx+0.5) * nodeWidth;
			var endPx:int = (maxx+0.5) * nodeWidth;
			var startPy:int = (miny+0.5) * nodeHeight;
			var endPy:int = (maxy + 0.5) * nodeHeight;
			var node:Node;
			
			//x轴采样:
			var px:int; var py:int;
			var acnode:Node;
			node = s.x < e.x?s:e;
			var i:int;
			for (i = minx; i <= maxx; i++ ) {
				px = i * nodeWidth + 1;
				if (px>=startPx && px<= endPx)
				{
					py = getPy(px);
					//trace("x1 " + px + " " + py);
					acnode = _grid.getNodeByXY(px, py);
					if (!acnode ||!acnode.walkAble) return false;
					if (checkCorner(acnode)) return false;
					node = acnode;
				}
				
				px = (i + 1) * nodeWidth - 1;
				if (px >= startPx && px <= endPx)
				{
					py = getPy(px);
					//trace("x2 " + px + " " + py);
					acnode = _grid.getNodeByXY(px, py);
					if (!acnode||!acnode.walkAble) return false;
					if (checkCorner(acnode)) return false;
					node = acnode;
				}
				
			}
			
			//--y轴采样:
			//if (_k == 0) return true;
			acnode = s.y < e.y?s:e;
			for (i = miny; i <= maxy; i++ ) {
				py = i * nodeHeight + 1;
				if (py >= startPy && py <= endPy) {
					px = getPx(py);
					//trace("y1 " + px + " " + py);
					acnode = _grid.getNodeByXY(px, py);
					if (!acnode||!acnode.walkAble) return false;
					if (checkCorner(acnode)) return false;
					node = acnode;
				}
				
				py = (i + 1) * nodeHeight -1;
				if (py >= startPy && py <= endPy) {
					px = getPx(py);
					//trace("y2 " + px + " " + py);
					acnode = _grid.getNodeByXY(px, py);
					if (!acnode||!acnode.walkAble) return false;
					if (checkCorner(acnode)) return false;
					node = acnode;
				}
				
			}
			
			return true;
			
			
			function getPx(yy:Number):Number {
				
				//if (_isPanX) return _panXvalue;
				if (_isPanY) return _panYvalue;
				return (yy - _b) / _k;
			}
			function getPy(xx:Number):Number {
				if (_isPanX) return _panXvalue;
				//if (_isPanY) return _panYvalue;
				return _k * xx + _b;
			}
			function checkCorner(n:Node):Boolean {
				var face:int = getface(n);
				var c1:Node; var c2:Node;
				switch(face) {
					case 4:
					c1 = nodes[n.y][n.x - 1] as Node;
					c2 = nodes[n.y - 1][n.x ] as Node;
					break;
					case -2:
					c1 = nodes[n.y][n.x - 1] as Node;
					c2 = nodes[n.y +1][n.x ] as Node;
					break;
					case -4:
					c1 = nodes[n.y][n.x + 1] as Node;
					c2 = nodes[n.y +1][n.x ] as Node;
					break;
					case 2:
					c1 = nodes[n.y][n.x + 1] as Node;
					c2 = nodes[n.y +1][n.x ] as Node;
					break;
					default :
					return false;
					break;
				}
				if (!c1.walkAble && !c2.walkAble) return true;
				return false;
			}
			function getface(n:Node):int {
				var result:int=(n.y - node.y) * 3 + (n.x - node.x);
				return result;
			}
			
			/*
			 * arrange.clear();
			var node:Node = s;
			var test:Node;
			var sex:Number = ((e.x - s.x) * nodeWidth);
			var sey:Number = ((e.y - s.y) * nodeHeight);
			
			var minx:int = Math.min(e.x, s.x);
			var maxx:int = Math.max(e.x, s.x);
			var miny:int = Math.min(s.y, e.y);
			var maxy:int = Math.max(s.y,e.y);
			
			while (node != e) {
				
				var sx:int = node.x - 1;
				var ex:int = node.x + 1;
				var sy:int = node.y - 1;
				var ey:int = node.y + 1;
				if (sx < minx) sx = minx;
				if (ex > maxx) ex = maxx;
				if (sy < miny) sy = miny;
				if (ey > maxy) ey = maxy;
				//trace("sx " + sx + " ex " + ex + " sy " + sy + "  ey " + ey);
				for (var i:int = sx; i <= ex; i++ ) {
					
					for (var h:int = sy; h <= ey; h++ ) {
						test = nodes[h][i]as Node;
						if (test.visited || test==node) continue;
						test.visited = true;
						var corrs:Boolean = checkCorrs();
						//trace(" x "+i+"  y "+h +" " +corrs);
						if (corrs) {
							if (!test.walkAble) {
								//trace("WILL RETURN FALSE!!");
							return false;
								}
							test.f = distToEnd();
							arrange.put(test);
							}
					}
				}
				node = arrange.pop() as Node;
				
				//trace("sx " + sx + "  ex " + ex + "  sy " + sy + "  ey " + ey);
				if (node == null) return true;
			
			}
			//trace("Muset3");
			return true;
			 
			
			function checkCorrs():Boolean {
				//trace("cosr");
				var lt:Point = new Point(test.x * nodeWidth, test.y * nodeHeight);
				var rt:Point = lt.clone(); rt.x += nodeWidth;
				var lb:Point = lt.clone(); lb.y += nodeHeight;
				var rb:Point = lb.clone(); rb.x += nodeWidth;
				var status:int = isUnder(lt);
				//trace(status);
				var st_rt:int = isUnder(rt);
				//trace(st_rt);
				if (st_rt != 0) {
					if (status == 0) {
						status = st_rt;
					}else if (status != st_rt) {  return true };
				}
				var st_lb:int = isUnder(lb);
				//trace(st_lb);
				if (st_lb != 0) {
					if (status == 0) {
						status = st_lb;
					}else if (status != st_lb) {  return true };
				}
				var st_rb:int = isUnder(rb);
				//trace(st_rb);
				if (st_rb != 0) {
				 if (status != st_rb) {  return true };
				}
				//trace(status, st_rt, st_lb, st_rb);
			
				return false;
			}
			function distToEnd():uint {
				var disx:int = (node.x - test.x);
				var disy:int = (node.y-test.y);
				return disx * disx + disy * disy;
			}
			function isUnder(p:Point):int {
				
				var result:Number = sey * (p.x - (s.x+0.5)*nodeWidth) - (p.y - (s.y+0.5)*nodeHeight) * sex;
				if (result>0)  result = 1;
				if (result<0)  result = -1;
				return result;
			}
			* */
		}
		
	}

}